home *** CD-ROM | disk | FTP | other *** search
- /* $Id: psorder.c,v 1.1.1.1 1996/06/07 01:00:44 sverrehu Exp $ */
- /**************************************************************************
- *
- * FILE psorder.c
- * MODULE OF psorder - move negative pages in a .ps-file
- *
- * DESCRIPTION Program for moving negative numbered pages in a
- * postscript-file to some given/suitable location.
- *
- * Primarily written to move the table of contents of
- * files generated by texi2dvi -> dvips from the end
- * of the file to after the title pages.
- *
- * WRITTEN BY Sverre H. Huseby <sverrehu@ifi.uio.no>
- *
- **************************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include <shhmsg.h>
- #include <shhopt.h>
-
- #include "util.h"
-
- #define MAXPAGES 2000
- #define MAXLINELEN 4096
-
- #define PSID "%!PS-Adobe-2.0"
- #define PSPAGE "%%Page:"
- #define PSTRAIL "%%Trailer"
- #define PSEOF "%%EOF"
-
- /**************************************************************************
- * *
- * P R I V A T E D A T A *
- * *
- **************************************************************************/
-
- static FILE *inFile, *outFile;
- typedef struct {
- int p1, /* program generated page number */
- p2; /* page sequence number */
- long start, /* byte offset of this page */
- nlines; /* number of lines for this page */
- } psPage;
- static psPage page[MAXPAGES], *ordered[MAXPAGES];
- static int nPages = 0;
- static char line[MAXLINELEN + 1];
- static long offsTrail = 0L, nlinesHead = 0L;
-
-
-
- /**************************************************************************
- * *
- * P R I V A T E F U N C T I O N S *
- * *
- **************************************************************************/
-
- /*-------------------------------------------------------------------------
- *
- * NAME scanFile
- *
- * FUNCTION Locate all pages in a PostScript-file.
- *
- * SYNOPSIS void scanFile(void);
- *
- * DESCRIPTION The file is left open, with the current location at the
- * end of the file. All pageinfo is stored in the global
- * structure.
- *
- */
- static void scanFile(void)
- {
- long l = 0L, last = 0L;
- psPage *p;
-
- msgVerbose(1, "scanning file to find page offsets\n");
- if (fgets(line, MAXLINELEN, inFile) == NULL)
- msgFatal("unexpected end of file\n");
- if (strncmp(line, PSID, strlen(PSID)) != 0)
- msgFatal("input is not recognized as a PostScript-file\n");
- while (fgets(line, MAXLINELEN, inFile) != NULL) {
- if (strncmp(line, PSTRAIL, strlen(PSTRAIL)) == 0
- || strncmp(line, PSEOF, strlen(PSEOF)) == 0)
- break;
- if (strncmp(line, PSPAGE, strlen(PSPAGE)) == 0) {
- if (nPages == MAXPAGES)
- msgFatal("too many pages.\n");
- if (nPages)
- page[nPages - 1].nlines = l - 1;
- else
- nlinesHead = l + 1;
- l = 0L;
- p = &page[nPages];
- if (sscanf(line + strlen(PSPAGE), "%d %d\n", &p->p1, &p->p2) != 2)
- msgFatal("two pagenumbers expected after %s\n", PSPAGE);
- p->start = ftell(inFile);
- ++nPages;
- }
- ++l;
- last = ftell(inFile);
- }
- if (!nPages)
- msgFatal("no pagestarts recognized in input\n");
- page[nPages - 1].nlines = l - 1;
- offsTrail = last;
- }
-
-
-
- /*-------------------------------------------------------------------------
- *
- * NAME arrangePages
- *
- * FUNCTION Arrange the pages in `correct' order.
- *
- * SYNOPSIS void arrangePages(int pageno);
- *
- * INPUT pageno The new number of the first negative page,
- * counting from 1.
- *
- */
- static void arrangePages(int pageno)
- {
- int n, q;
-
- if (pageno < 0) {
- /*
- * find a suitable location.
- * for files generated by texi2dvi -> dvips, this is where
- * the page counter starts at 1 the second time.
- */
- for (q = 1; q < nPages; q++)
- if (page[q].p1 == 1)
- break;
- if (q == nPages)
- msgFatal("unable to find good location for the negative pages.\n");
- pageno = page[q].p2;
- msgVerbose(1, "negative pages will be inserted from page %d\n",
- pageno);
- }
- msgVerbose(1, "rearranging\n");
- for (q = 0; q < pageno - 1; q++)
- ordered[q] = &page[q];
- for (n = q = pageno - 1 ; q < nPages; q++)
- if (page[q].p1 < 0)
- ordered[n++] = &page[q];
- for (q = pageno - 1 ; q < nPages; q++)
- if (page[q].p1 >= 0)
- ordered[n++] = &page[q];
- for (q = 0; q < nPages; q++)
- ordered[q]->p2 = q + 1;
- }
-
-
-
- /*-------------------------------------------------------------------------
- *
- * NAME writeFile
- *
- * FUNCTION Output the pages in the current order.
- *
- * SYNOPSIS void writeFile(void);
- *
- */
- static void writeFile(void)
- {
- int q, w;
- psPage *p;
-
- msgVerbose(1, "writing rearranged pages\n");
- rewind(inFile);
- for (q = 0; q < nlinesHead; q++) {
- if (fgets(line, MAXLINELEN, inFile) == NULL)
- msgFatal("unexpected end of file\n");
- if (fputs(line, outFile) == EOF)
- msgFatalPerror("fputs");
- }
- for (q = 0; q < nPages; q++) {
- p = ordered[q];
- fseek(inFile, p->start, SEEK_SET);
- fprintf(outFile, "%s %d %d\n", PSPAGE, p->p1, p->p2);
- for (w = 0; w < p->nlines; w++) {
- if (fgets(line, MAXLINELEN, inFile) == NULL)
- msgFatal("unexpected end of file\n");
- if (fputs(line, outFile) == EOF)
- msgFatalPerror("fputs");
- }
- }
- fseek(inFile, offsTrail, SEEK_SET);
- while (fgets(line, MAXLINELEN, inFile) != NULL)
- if (fputs(line, outFile) == EOF)
- msgFatalPerror("fputs");
- fclose(outFile);
- fclose(inFile);
- }
-
-
-
- /*-------------------------------------------------------------------------
- *
- * NAME usage
- *
- * FUNCTION Display usage, and abort program.
- *
- * RETURNS Never returns.
- *
- */
- static void usage(void)
- {
- printf(
- "usage: %s [option ...] [infile [outfile]]\n"
- "\n"
- " -p, --page-number=NUM set new page number of first negative page\n"
- " -f, --force force overwrite of existing file\n"
- " -v, --verbose verbosly list what is going on\n"
- " -h, --help display this help and exit\n"
- " -V, --version output version information and exit\n"
- "\n"
- "If no --page-number is given, the program tries to find a good place.\n"
- "\n",
- msgGetName()
- );
- exit(0);
- }
-
-
-
- /*-------------------------------------------------------------------------
- *
- * NAME version
- *
- * FUNCTION Display version information, and abort program.
- *
- * RETURNS Never returns.
- *
- */
- static void version(void)
- {
- printf("%s " VERSION " by Sverre H. Huseby, Norway\n", msgGetName());
- exit(0);
- }
-
-
-
- /**************************************************************************
- * *
- * P U B L I C F U N C T I O N S *
- * *
- **************************************************************************/
-
- int main(int argc, char *argv[])
- {
- static int verbose = 0, force = 0, pageNumber = -1;
- optStruct opt[] = {
- /* short long type var/func special */
- { 'p', "page-number", OPT_INT, &pageNumber,0 },
- { 'f', "force", OPT_FLAG, &force, 0 },
- { 'v', "verbose", OPT_FLAG, &verbose, 0 },
- { 'h', "help", OPT_FLAG, usage, OPT_CALLFUNC },
- { 'V', "version", OPT_FLAG, version, OPT_CALLFUNC },
- { 0, 0, OPT_END, 0, 0 } /* no more options */
- };
-
- msgSetName(argv[0]);
- optParseOptions(&argc, argv, opt, 0);
- msgSetVerbose(verbose);
-
- if (argc == 1) {
- inFile = fileOpenReadSeekable(NULL);
- outFile = fileOpenWrite(NULL, force);
- } else if (argc <= 3) {
- inFile = fileOpenReadSeekable(argv[1]);
- outFile = fileOpenWrite(argc == 2 ? NULL : argv[2], force);
- } else
- usage();
-
- scanFile();
- arrangePages(pageNumber);
- writeFile();
-
- return 0;
- }
-